import type {ErrorMessageMode} from '/#/axios';
import {defineStore} from 'pinia';
import {store} from '/@/store';
import {RoleEnum} from '/@/enums/roleEnum';
import {PageEnum} from '/@/enums/pageEnum';
import {thirdAuthLogin} from '/@/api/auth'
import {TenantConfig} from '/@/api/sys/model/tenantModel';
import {
  DB_DICT_DATA_KEY,
  LAST_ROUTE_PATH,
  ROLES_KEY,
  TENANT_CONFIG_KEY,
  USER_INFO_KEY
} from '/@/enums/cacheEnum';
import {
  getCacheToken,
  setCacheDataDictKey,
  setCacheRole,
  setCacheToken,
  setCacheUserInfo,
  updateCacheLoginUser
} from '/@/utils/cache/module/auth';
import {getCache, getCacheByDynKey, setCacheByDynKey} from '/@/utils/cache/index';
import {
  GetUserInfoModel,
  LoginParams,
  LoginResultModel,
  ThirdLoginParams,
  UserInfo
} from '/@/api/sys/model/userModel';
import {doLogout, getUserInfo, loginApi, phoneLoginApi, switchTenant} from '/@/api/sys/user';
import {useI18n} from '/@/hooks/web/useI18n';
import {useMessage} from '/@/hooks/web/useMessage';
import {router} from '/@/router';
import {usePermissionStore} from '/@/store/modules/permission';
import {RouteRecordRaw} from 'vue-router';
import {PAGE_NOT_FOUND_ROUTE} from '/@/router/routes/basic';
import {isArray} from '/@/utils/is';
import {useGlobSetting} from '/@/hooks/setting';
import {useSso} from '/@/hooks/web/useSso';
import {queryAllDictItems} from '/@/views/system/dict/dict.api';
import mitt, {Emitter} from '/@/utils/mitt';

const { t } = useI18n();
const { createMessage, notification } = useMessage();

// import { useRedo } from '/@/hooks/web/usePage';
// const redo = useRedo();
interface UserState {
  userInfo: Nullable<UserInfo>;
  selectTenant?: TenantConfig | any;
  token?: string;
  roleList: RoleEnum[];
  dictItems?: [];
  sessionTimeout?: boolean;
  lastUpdateTime: number;
  multiDept?: string | number;
  deptList?:[];
  tenantList?: [];
  isLogin: boolean
  loginId: string;
  emitter: Emitter;
}

export const useUserStore = defineStore({
  id: 'app-user',
  state: (): UserState => ({
    // 用户信息
    userInfo: null,
    // 选择的租户
    selectTenant: null,
    // token
    token: undefined,
    // 角色列表
    roleList: [],
    // 字典
    dictItems: [],
    // session过期时间
    sessionTimeout: false,
    // Last fetch time
    lastUpdateTime: 0,
    isLogin: false,
    loginId: '',
    // 全局事件 think gem
    emitter: mitt(),

  }),
  getters: {
    getUserInfo(): UserInfo {
      return this.userInfo || getCache<UserInfo>(USER_INFO_KEY) || {};
    },
    getSelectTenant(): TenantConfig {
      return this.selectTenant || getCacheByDynKey<TenantConfig>(TENANT_CONFIG_KEY) || {};
    },

    getIsAdminTenant(): boolean {
      const tenant = this.selectTenant || getCacheByDynKey<TenantConfig>(TENANT_CONFIG_KEY) || {};
      return tenant.tenantId ===  useGlobSetting().platformTenantId
    },

    getToken(): string {
      return this.token || getCacheToken();
    },
    getAllDictItems(): []{
      return this.dictItems || getCache(DB_DICT_DATA_KEY);
    },
    getRoleList(): RoleEnum[] {
      return this.roleList.length > 0 ? this.roleList : getCache<RoleEnum[]>(ROLES_KEY);
    },
    getSessionTimeout(): boolean {
      return !!this.sessionTimeout;
    },
    getLastUpdateTime(): number {
      return this.lastUpdateTime;
    },
    getLoginId() : string {
      return this.loginId;
    },
    getIsLogin() : boolean {
      return !!this.isLogin;
    },
    getEmitter(): any {
      return this.emitter;
    },
  },
  actions: {
    setToken(info: string | undefined) {
      this.token = info ? info : ''; // for null or undefined value
      setCacheToken(info);
    },
    setLoginId(info: string | undefined) {
      this.loginId = info ? info : ''; 
      setCacheToken(info);
    },

    // 设置选择的租户
    setSelectTenant(tenantInfo: any) {
      const oldTenant = this.selectTenant || getCacheByDynKey<TenantConfig>(TENANT_CONFIG_KEY) || {};
      if (tenantInfo) {
        const tmpTenant = {
          ...oldTenant, ...tenantInfo, tenantId: tenantInfo.id,
        }
        this.selectTenant = tmpTenant
        setCacheByDynKey(TENANT_CONFIG_KEY, this.selectTenant);
      } else {
        setCacheByDynKey(TENANT_CONFIG_KEY, undefined);
      }
    },

    // 切换租户
    async switchTenant(tenantId: string, isLogin = false) {
      if (!isLogin) {
        await switchTenant({tenantId})
      }
      
      this.setSelectTenant({id: tenantId})
    },

    // 前一个工作空间最后一次的路由
    setLastRoutePath(info: string | undefined) {
      setCacheByDynKey(LAST_ROUTE_PATH + this.userInfo?.currentTenantId + this.userInfo?.currentAppId, info);
    },
    setRoleList(roleList: RoleEnum[]) {
      this.roleList = roleList;
      setCacheRole(roleList);
    },
    setUserInfo(info: UserInfo | null) {
      this.userInfo = info;
      this.lastUpdateTime = new Date().getTime();
      setCacheUserInfo(info);

      updateCacheLoginUser({
        userInfo: this.userInfo,
      })
    }, 
    setAllDictItems(dictItems) {
      this.dictItems = dictItems;
      setCacheDataDictKey(dictItems);
    },
    setSessionTimeout(flag: boolean) {
      this.sessionTimeout = flag;
    },
    resetState() {
      this.userInfo = null;
      this.dictItems = [];
      this.token = '';
      this.roleList = [];
      this.sessionTimeout = false;
    },
    /**
     * 登录事件
     */
    async login(
      params: LoginParams & {
        goHome?: boolean;
        mode?: ErrorMessageMode;
      },
    ): Promise<LoginResultModel | null> {
      try {
        const { goHome = true, mode, ...loginParams } = params;
        const authLoginData = await loginApi(loginParams, mode);
        const { loginId } = authLoginData.additionalParameters
        // 这里先设置成false, 避免用户没有选择租户就刷新页面出现问题
        this.loginId = loginId
        this.isLogin = false
        // return this.afterLoginAction(goHome, authLoginData);
        return authLoginData
      } catch (error) {
        return Promise.reject(error);
      }
    }, 

    /**
     * 登录完成处理
     * @param goHome
     */
    async afterLoginAction(goHome?: boolean, authLoginData?: any ) : Promise<any | null> {
      console.log('============== authLoginData', authLoginData);
      
      console.time("load_menu_time")
      if (!this.getToken) {
        console.log('token is null');
        return null;
      }
      //获取用户信息
      const useProfile = await this.getUserInfoAction();
      const sessionTimeout = this.sessionTimeout;
      if (sessionTimeout) {
        this.setSessionTimeout(false);
      } else {
        const permissionStore = usePermissionStore();
        if (!permissionStore.isDynamicAddedRoute) {
          const routes = await permissionStore.buildRoutesAction();
          
          routes.forEach((route) => {
            router.addRoute(route as unknown as RouteRecordRaw);
          });
          router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
          permissionStore.setDynamicAddedRoute(true);
        }
        console.log('authLoginData', authLoginData);
        this.isLogin = true
        this.loginId = authLoginData.loginId
        
        // @ts-ignore
        setCacheUserInfo(useProfile?.userInfo)

        updateCacheLoginUser({
          isLogin: this.isLogin,
          loginId: this.loginId,
          userInfo: this.userInfo,
        })

        console.timeEnd('load_menu_time');
        
        const queryParams = router.currentRoute.value.query
        const redirect = queryParams?.redirect as string || queryParams?.backUrl as string
        const pagePath = (redirect || (useProfile && useProfile.userInfo?.homePath) || PageEnum.BASE_HOME)
        console.log('pagePath', pagePath);
        
        goHome && (await router.replace((pagePath === '/' || pagePath === '') ? PageEnum.BASE_HOME : pagePath));
      }
      return authLoginData;
    },

    /**
     * 手机号登录
     * @param params
     */
    async phoneLogin(
      params: LoginParams & {
        goHome?: boolean;
        mode?: ErrorMessageMode;
      },
    ): Promise<GetUserInfoModel | null> {
      try {
        const { goHome = true, mode, ...loginParams } = params;
        const data = await phoneLoginApi(loginParams, mode);
        const { token } = data;
        // save token
        this.setToken(token);
        return this.afterLoginAction(goHome,data);
      } catch (error) {
        return Promise.reject(error);
      } 
    },
    /**
     * 获取用户信息
     */
    async getUserInfoAction(): Promise<GetUserInfoModel | null> {
      if (!this.getToken) {
        return null;
      }
      let data = await getUserInfo() as GetUserInfoModel;
      const {roles, userInfo, tenant} = data;
      this.setSelectTenant(tenant)
      if(roles) {
        if (isArray(roles)) {
          const roleList = roles.map((item) => item.value) as RoleEnum[];
          this.setRoleList(roleList);
        } else {
          this.setRoleList([]);
        }
      }
      this.setUserInfo(userInfo as UserInfo);
      const sysAllDictItems = await queryAllDictItems();
      // 添加字典信息到缓存
      if(sysAllDictItems && sysAllDictItems.data) {
        this.setAllDictItems(sysAllDictItems.data);
      }
      console.log("userInfo: ", userInfo);
      return data;
    },

    /**
     * 退出登录
     */
    async logout(goLogin = false) {
      console.log('logout');
      
      if (this.getToken) {
        try {
          await doLogout();
        } catch {
          console.log('注销Token失败');
        }
      }
      this.setToken('');
      setCacheToken(null);
      setCacheUserInfo(null);
      this.setSessionTimeout(false);
      this.setUserInfo(null);
      this.setSelectTenant(null)

      //如果开启单点登录,则跳转到单点统一登录中心
      const openSso = useGlobSetting().openSso;
      if(openSso=='true'){
        await useSso().ssoLoginOut();
      }

      const currentRoute = router.currentRoute.value;
      let redirect : string = PageEnum.BASE_HOME;
      if (currentRoute.path !== '/' && currentRoute.path !== PageEnum.BASE_LOGIN) {
        redirect = decodeURIComponent(currentRoute.fullPath)
      }

      if (goLogin) {
        router.replace({
          path: PageEnum.BASE_LOGIN,
          query: { redirect }
        }).then(e => location.reload() ) // 跳转之后刷新页面, 避免管理员更改一些配置, 自动退出或者超时退出到登录页面, 配置还是老的问题
      }
    },
  /**
   * 登录事件
   */
   async ThirdLogin(
        params: ThirdLoginParams & {
        goHome?: boolean;
        mode?: ErrorMessageMode;
       },
      ): Promise<any | null> {
      try {
          const { goHome = true, ...ThirdLoginParams } = params;
          const data = await thirdAuthLogin(ThirdLoginParams);
          const { authToken } = data;
          // save token
          this.setToken(authToken?.accessToken);
          // return this.afterLoginAction(goHome, data);
          return data
      } catch (error) {
          return Promise.reject(error);
      }
   },
    /**
     * 退出询问
     */
    confirmLoginOut() {
      const { createConfirm } = useMessage();
      const { t } = useI18n();
      createConfirm({
        iconType: 'warning',
        title: t('sys.app.logoutTip'),
        content: t('sys.app.logoutMessage'),
        onOk: async () => {
          await this.logout(true);
        },
      });
    },
  },
});

// Global emit by think gem
export function useEmitter() {
  return useUserStore().emitter;
}

// Need to be used outside the setup
export function useUserStoreWithOut() {
  return useUserStore(store);
}
